﻿// Copyright 2009 William P. Hickey Jr. and William U. Walker
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//     
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//  
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Xml.Serialization;
using System.ComponentModel;

namespace CSReporter
{
    /// <summary>
    /// 
    /// </summary>
    public class ConfigData : INotifyPropertyChanged
    {
        private string version;             // Current version
        private string dataDir;             // Default directory for all datafiles
        private string sqlServerName;       // SQLServer machine and instance name
        private string sqlDatabase;         // SQLServer database name
        private string sqlLogin;            // SQLServer login if not using Windows authentication
        private string sqlPassword;         // SQLServer password if not using Windows authentication
        private bool useWindowsAuth;        // true = use Windows authentication
        private bool saveToSql;             // true = mirror all data saves to SQLServer
        private double kmlRange;            // Range value to use in KML files
        private string kmlWhiteIcon;        // White icon string for KML files
        private string kmlGreenIcon;        // Green icon string for KML files
        private string kmlYellowIcon;       // Yellow icon string for KML files
        private string kmlRedIcon;          // Red icon string for KML files
        private string kmlFileLocation;     // Directory or network location to save the KML file
        private bool kmlFlyToView;          // KML file Fly To View value
        private int kmlRefreshInterval;     // KML file Refresh Interval value;
        private bool saveToKml;             // true = mirror all data saves to KML file
        private string ftpKmlHost;          // Hostname or IP of FTP server for KML publishing
        private string ftpKmlPath;          // Path in the FTP server
        private string ftpKmlLogin;         // FTP login name 
        private string ftpKmlPassword;      // FTP login password
        private int ftpKmlPort;             // FTP port number
        private bool ftpKmlPublish;         // true = periodically publish a KML file
        private string eventName;           // Name of an ongoing event, such as "Practice Net"
        private PacketControlType interfaceType; // 0 = Disabled, 1 = AGWPE, 2 = Serial Port
        private bool connectOnStart;        // true = connect to AGWPE or the TNC when CSReporter starts
        private string agwHost;             // Hostname or IP of a machine running AGWPE
        private int agwPort;                // AGWPE port number
        private int agwVhfUhfRadio;         // AGWPE radio port to use for UHF/VHF transmissions
        private int agwHfRadio;             // AGWPE radio port to use for HF transmissions
        private string callSign;            // FCC assigned call sign of the station in use
        private int beaconInterval;         // Number of minutes between beacon transmissions
        private bool beaconOnStart;         // true = start transmitting a beacon when CSReporter starts
        private string beaconText;          // Text message for beacon transmissions
        private int txPower;                // APRS transmitter power value
        private int haat;                   // APRS height above average terrain value
        private int antGain;                // APRS antennae gain value
        private int antDirectivity;         // APRS antennae directivity value
        private double latitude;            // Current latitude of the station
        private double longitude;           // Current longitude of the station
        private string digiPath;            // Default digipath
        private string reportToCall;        // Default station to send CSReports to
        private bool noSound;               // true = do not play sounds

        public string Version               // Configuration file version
        {
            get{return version;}
            set {
                version = value;
                this.NotifyPropertyChanged("Version");
            }
        }

        public string DataDir               // Default directory for all datafiles
        {
            get{return dataDir;}
            set {
                dataDir = value;
                this.NotifyPropertyChanged("DataDir");
            }
        }

        public string SqlServerName         // SQLServer machine and instance name
        {
            get{return sqlServerName;}
            set {
                sqlServerName = value;
                this.NotifyPropertyChanged("SqlServerName");
            }
        }

        public string SqlDatabase           // SQLServer database name
        {
            get{return sqlDatabase;}
            set {
                sqlDatabase = value;
                this.NotifyPropertyChanged("SqlDatabase");
            }
        }

        public string SqlLogin              // SQLServer login if not using Windows authentication
        {
            get{return sqlLogin;}
            set {
                sqlLogin = value;
                this.NotifyPropertyChanged("SqlLogin");
            }
        }

        public string SqlPassword           // SQLServer password if not using Windows authentication
        {
            get{return sqlPassword;}
            set {
                sqlPassword = value;
                this.NotifyPropertyChanged("SqlPassword");
            }
        }

        public bool UseWindowsAuth          // true = use Windows authentication
        {
            get{return useWindowsAuth;}
            set {
                useWindowsAuth = value;
                this.NotifyPropertyChanged("UseWindowsAuth");
            }
        }

        public bool SaveToSql               // true = mirror all data saves to SQLServer
        {
            get{return saveToSql;}
            set {
                saveToSql = value;
                this.NotifyPropertyChanged("SaveToSql");
            }
        }

        public double KmlRange              // Range value to use in KML files
        {
            get{return kmlRange;}
            set {
                kmlRange = value;
                this.NotifyPropertyChanged("KmlRange");
            }
        }

        public string KmlWhiteIcon          // White icon string for KML files
        {
            get{return kmlWhiteIcon;}
            set {
                kmlWhiteIcon = value;
                this.NotifyPropertyChanged("KmlWhiteIcon");
            }
        }

        public string KmlGreenIcon          // Green icon string for KML files
        {
            get{return kmlGreenIcon;}
            set {
                kmlGreenIcon = value;
                this.NotifyPropertyChanged("KmlGreenIcon");
            }
        }

        public string KmlYellowIcon          // Yellow icon string for KML files
        {
            get{return kmlYellowIcon;}
            set {
                kmlYellowIcon = value;
                this.NotifyPropertyChanged("KmlYellowIcon");
            }
        }

        public string KmlRedIcon            // Red icon string for KML files
        {
            get{return kmlRedIcon;}
            set {
                kmlRedIcon = value;
                this.NotifyPropertyChanged("KmlRedIcon");
            }
        }

        public string KmlFileLocation       // Directory or network location to save the KML file
        {
            get{return kmlFileLocation;}
            set {
                kmlFileLocation = value;
                this.NotifyPropertyChanged("KmlFileLocation");
            }
        }

        public bool KmlFlyToView            // KML file Fly To View value
        {
            get{return kmlFlyToView;}
            set {
                kmlFlyToView = value;
                this.NotifyPropertyChanged("KmlFlyToView");
            }
        }

        public int KmlRefreshInterval       // KML file Refresh Interval value  
        {
            get{return kmlRefreshInterval;}
            set {
                kmlRefreshInterval = value;
                this.NotifyPropertyChanged("KmlRefreshInterval");
            }
        }

        public bool SaveToKml               // true = mirror all data saves to KML file
        {
            get{return saveToKml;}
            set {
                saveToKml = value;
                this.NotifyPropertyChanged("SaveToKml");
            }
        }

        public string FtpKmlHost            // Hostname or IP of FTP server for KML publishing
        {
            get{return ftpKmlHost;}
            set {
                ftpKmlHost = value;
                this.NotifyPropertyChanged("FtpKmlHost");
            }
        }

        public string FtpKmlPath            // Path in the FTP server
        {
            get{return ftpKmlPath;}
            set {
                ftpKmlPath = value;
                this.NotifyPropertyChanged("FtpKmlPath");
            }
        }

        public string FtpKmlLogin           // FTP login name 
        {
            get{return ftpKmlLogin;}
            set {
                ftpKmlLogin = value;
                this.NotifyPropertyChanged("FtpKmlLogin");
            }
        }

        public string FtpKmlPassword        // FTP login password
        {
            get{return ftpKmlPassword;}
            set {
                ftpKmlPassword = value;
                this.NotifyPropertyChanged("FtpKmlPassword");
            }
        }

        public int FtpKmlPort               // FTP port number
        {
            get{return ftpKmlPort;}
            set {
                ftpKmlPort = value;
                this.NotifyPropertyChanged("FtpKmlPort");
            }
        }

        public bool FtpKmlPublish           // true = periodically publish a KML file
        {
            get{return ftpKmlPublish;}
            set {
                ftpKmlPublish = value;
                this.NotifyPropertyChanged("FtpKmlPublish");
            }
        }

        public string EventName             // Name of an ongoing event, such as "Practice Net"
        {
            get{return eventName;}
            set {
                eventName = value == null ? null : value.Substring(0, Math.Min(value.Length, 100)).Trim().ToUpper();
                this.NotifyPropertyChanged("EventName");
            }
        }

        public PacketControlType InterfaceType // 0 = Disabled, 1 = AGWPE, 2 = Serial Port
        {
            get{return interfaceType;}
            set {
                interfaceType = value;
                this.NotifyPropertyChanged("InterfaceType");
            }
        }

        public bool ConnectOnStart          // true = connect to AGWPE or the TNC when CSReporter starts
        {
            get{return connectOnStart;}
            set {
                connectOnStart = value;
                this.NotifyPropertyChanged("ConnectOnStart");
            }
        }

        public string AgwHost               // Hostname or IP of a machine running AGWPE
        {
            get{return agwHost;}
            set {
                agwHost = value;
                this.NotifyPropertyChanged("AgwHost");
            }
        }

        public int AgwPort                  // AGWPE port number
        {
            get{return agwPort;}
            set {
                agwPort = value;
                this.NotifyPropertyChanged("AgwPort");
            }
        }

        public int AgwVhfUhfRadio           // AGWPE radio port to use for UHF/VHF transmissions
        {
            get{return agwVhfUhfRadio;}
            set {
                agwVhfUhfRadio = value;
                this.NotifyPropertyChanged("AgwVhfUhfRadio");
            }
        }

        public int AgwHfRadio               // AGWPE radio port to use for HF transmissions
        {
            get{return agwHfRadio;}
            set {
                agwHfRadio = value;
                this.NotifyPropertyChanged("AgwHfRadio");
            }
        }

        public string CallSign              // FCC assigned call sign of the station in use
        {
            get{return callSign;}
            set {
                callSign = value == null ? null : value.Substring(0, Math.Min(value.Length, 10)).Trim().ToUpper();
                this.NotifyPropertyChanged("CallSign");
            }
        }

        public int BeaconInterval           // Number of minutes between beacon transmissions
        {
            get{return beaconInterval;}
            set {
                beaconInterval = value;
                this.NotifyPropertyChanged("BeaconInterval");
            }
        }

        public bool BeaconOnStart           // true = start transmitting a beacon when CSReporter starts
        {
            get{return beaconOnStart;}
            set {
                beaconOnStart = value;
                this.NotifyPropertyChanged("BeaconOnStart");
            }
        }

        public string BeaconText            // Text message for beacon transmissions
        {
            get{return beaconText;}
            set {
                beaconText = value == null ? null : value.Substring(0, Math.Min(value.Length, 43)).Trim();
                this.NotifyPropertyChanged("BeaconText");
            }
        }

        public int TxPower                  // APRS transmitter power value
        {
            get{return txPower;}
            set {
                txPower = value;
                this.NotifyPropertyChanged("TxPower");
            }
        }

        public int Haat                     // APRS height above average terrain value
        {
            get{return haat;}
            set {
                haat = value;
                this.NotifyPropertyChanged("Haat");
            }
        }

        public int AntGain                  // APRS antennae gain value
        {
            get{return antGain;}
            set {
                antGain = value;
                this.NotifyPropertyChanged("AntGain");
            }
        }

        public int AntDirectivity           // APRS antennae directivity value
        {
            get{return antDirectivity;}
            set {
                antDirectivity = value;
                this.NotifyPropertyChanged("AntDirectivity");
            }
        }

        public double Latitude              // Current latitude of the station
        {
            get{return latitude;}
            set {
                latitude = value;
                this.NotifyPropertyChanged("Latitude");
            }
        }

        public double Longitude             // Current longitude of the station
        {
            get{return longitude;}
            set {
                longitude = value;
                this.NotifyPropertyChanged("Longitude");
            }
        }

        public string DigiPath              // Default digipath
        {
            get{return digiPath;}
            set {
                digiPath = value == null ? null : value.Substring(0, Math.Min(value.Length, 100)).Trim().ToUpper();
                this.NotifyPropertyChanged("DigiPath");
            }
        }

        public string ReportToCall          // Default station to send CSReports to
        {
            get { return reportToCall; }
            set
            {
                reportToCall = value == null ? null : value.Substring(0, Math.Min(value.Length, 10)).Trim().ToUpper();
                this.NotifyPropertyChanged("ReportToCall");
            }
        }

        public bool NoSound                 // true = do not play sounds
        {
            get { return noSound; }
            set
            {
                noSound = value;
                this.NotifyPropertyChanged("NoSound");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Loads configuration data into the provided configDataSet structure.
        /// </summary>
        public ConfigData()
        {
            version = "0.3.0.34";       // Current version
                                        // Default directory for all datafiles
            dataDir = System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\CSReporter";
            sqlServerName = "";         // SQLServer machine and instance name
            sqlDatabase = "";           // SQLServer database name
            sqlLogin = "";              // SQLServer login if not using Windows authentication
            sqlPassword = "";           // SQLServer password if not using Windows authentication
            useWindowsAuth = true;      // true = use Windows authentication
            saveToSql = false;          // true = mirror all data saves to SQLServer
            kmlRange = 50000;           // Range value to use in KML files
            kmlWhiteIcon = "";          // White icon string for KML files
            kmlGreenIcon = "";          // Green icon string for KML files
            kmlYellowIcon = "";         // Yellow icon string for KML files
            kmlRedIcon = "";            // Red icon string for KML files
            kmlFileLocation = "";       // Directory or network location to save the KML file
            kmlFlyToView = true;        // KML file Fly To View value
            kmlRefreshInterval = 10;    // KML file Refresh Interval value = "";
            saveToKml = false;          // true = mirror all data saves to KML file
            ftpKmlHost = "";            // Hostname or IP of FTP server for KML publishing
            ftpKmlPath = "";            // Path in the FTP server
            ftpKmlLogin = "";           // FTP login name 
            ftpKmlPassword = "";        // FTP login password
            ftpKmlPort = 21;            // FTP port number
            ftpKmlPublish = false;      // true = periodically publish a KML file
            eventName = "";             // Name of an ongoing event, such as "Practice Net"
            interfaceType = PacketControlType.Disabled; // 0 = Disabled, 1 = AGWPE, 2 = Serial Port
            connectOnStart = false;     // true = connect to AGWPE or the TNC when CSReporter starts
            agwHost = "localhost";      // Hostname or IP of a machine running AGWPE
            agwPort = 8000;             // AGWPE port number
            agwVhfUhfRadio = 1;         // AGWPE radio port to use for UHF/VHF transmissions
            agwHfRadio = 1;             // AGWPE radio port to use for HF transmissions
            callSign = "";              // FCC assigned call sign of the station in use
            beaconInterval = 30;        // Number of minutes between beacon transmissions
            beaconOnStart = false;      // true = start transmitting a beacon when CSReporter starts
            beaconText = "CSReporter";  // Text message for beacon transmissions
            txPower = 0;                // APRS transmitter power value
            haat = 0;                   // APRS height above average terrain value
            antGain = 0;                // APRS antennae gain value
            antDirectivity = 0;         // APRS antennae directivity value
            latitude = 0;               // Current latitude of the station
            longitude = 0;              // Current longitude of the station
            digiPath = "";              // Default digipath, such as "WIDE2-2"
            reportToCall = "";          // Default station to send CSReports to
            noSound = false;            // true = do not play sounds
        }

        private void NotifyPropertyChanged(string name)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(name));
        }
    }

    public class ConfigList : BindingList<ConfigData>
    {
        // Static initialization ensures thread safety.
        private static readonly ConfigList singletonInstance = new ConfigList();

        private ConfigList() { }

        public static ConfigList GetConfigList()
        {
            if (singletonInstance.Items.Count == 0)
                singletonInstance.Add(new ConfigData());
            return singletonInstance;
        }

        public void ReadXml()
        {
            string fileName = System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\CSReporter\config.xml";
            if (File.Exists(fileName))
            {
                Clear();
                XmlSerializer deserializer = new XmlSerializer(typeof(List<ConfigData>));
                using(TextReader textReader = new StreamReader(fileName))
                    foreach (ConfigData cd in (List<ConfigData>)deserializer.Deserialize(textReader))
                        Add(cd);
            }
        }

        public void WriteXml()
        {
            string fileName = System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\CSReporter\config.xml";
            if (!Directory.GetParent(fileName).Exists)
                Directory.CreateDirectory(System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\CSReporter");
            if (Directory.GetParent(fileName).Exists)
            {
                XmlSerializer serializer = new XmlSerializer(typeof(List<ConfigData>));
                using (TextWriter textWriter = new StreamWriter(fileName))
                    serializer.Serialize(textWriter, Items);
            }
        }
    }
}
